﻿using System;
using System.Diagnostics;

namespace MyUtils.Performance
{
	internal class ProfilingSection : IDisposable
	{
		readonly ProfilingHelperInstance _profiler;
		readonly string _section;
		readonly ProfilingNode _currentNode;
		readonly Stopwatch _sw;

		bool _sectionDisposed;

		internal ProfilingSection(ProfilingHelperInstance profiler, string section, ProfilingNode currentNode)
		{
			_profiler = profiler;
			_section = section;
			_currentNode = currentNode;
			_sw = Stopwatch.StartNew();
		}

		#region IDisposable Members

		void IDisposable.Dispose()
		{
			EndOfSection();
		}

		#endregion

		void EndOfSection()
		{
			if (_sectionDisposed)
			{
				return;
			}

			_sw.Stop();
			_sectionDisposed = true;
			var time = _sw.Elapsed;
			lock (_profiler.Info)
			{
				TimeSpan total;
				_profiler.Info.TryGetValue(_section, out total);
				_profiler.Info[_section] = total + time;
				_profiler.Dirty = true;
			}

			_currentNode._timeHereActual += time;

			var node = _profiler.CurrentStack.Pop();
			if (node != _currentNode)
			{
				throw new Exception("Profiling node on a top of a stack is not a current node. You should close profiling sections in reverse order and from the same threads");
			}
		}
	}
}